
package horde.standard.resources.graphics;

import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.LayoutManager;
import java.util.ArrayList;

/**
 *
 * @author Andres Picazo
 */
public class StackLayout implements LayoutManager {

    public static final String putBesides = "besides";
    public static final String putBelow = "below";
    public static final String putAndExpand = "expand";

    private class Element {
        Component c; String location;
        public Element (Component c, String location) {
            this.c = c;
            this.location = location;
        }
    }

    private ArrayList<ArrayList<Element>> components;
    private int gap = 1;
    private int currentLine = -1; /* -1 indicates there is nothing  */
    private int requiredHeight = 0;
    private int expandableComponents = 0;

    public StackLayout () {
        components = new ArrayList<ArrayList<Element>>();
        requiredHeight = gap;
        currentLine = -1;
        expandableComponents = 0;
    }

    public StackLayout (int gap) {
        components = new ArrayList<ArrayList<Element>>();
        this.gap = gap;
        requiredHeight = gap;
        currentLine = -1;
        expandableComponents = 0;
    }

    public void addLayoutComponent(String name, Component comp) {
        /* Creates the arraylist for the first line */
        if (currentLine == -1) {
            components.add (new ArrayList<Element>());
            currentLine++; /* Current line = 0 */
            components.get(currentLine).add(new Element(comp, name));
            if (!name.equals(putAndExpand)) requiredHeight += comp.getPreferredSize().height + gap;
        }
        /* I already have at least one element */
        else {
            if (name.equals(putBesides)) {
                ArrayList<Element> line = components.get(currentLine);
                if (line.get(line.size()-1).location.equals(putAndExpand)) {
                    currentLine++;
                    /* Creates the new line */
                    components.add (new ArrayList<Element>());
                }
                components.get(currentLine).add(new Element(comp, name));
            }
            else {
                currentLine++;
                /* Creates the new line */
                components.add (new ArrayList<Element>());
                /* Adds the component */
                components.get(currentLine).add(new Element(comp, name));
                if (name.equals(putAndExpand)) expandableComponents++;
                else requiredHeight += comp.getPreferredSize().height + gap;
            }
        }
    }

    public void layoutContainer(Container parent) {
        /* Fix last element bug */
        if (components.get(components.size()-1).isEmpty()) components.remove(components.size()-1);
        /* Set bounds */
        int defX = gap, defY = gap;
        int maxW = parent.getWidth();
        int maxH = parent.getHeight();
        int x = defX, y = defY;
        for (ArrayList<Element> line : components) {
            int extraSpace = 0;
            if (line.size() == 1) {
                Component c = line.get(0).c;
//                c.setBounds(x, y, c.getPreferredSize().width, c.getPreferredSize().height);
                int compHeight = c.getPreferredSize().height;
                if (line.get(0).location.equals(putAndExpand)) {
                    compHeight = (maxH - requiredHeight) / expandableComponents;
                }
                c.setBounds(x, y, maxW - (gap*2), compHeight - gap);
//                y += c.getPreferredSize().height + gap;
                y += compHeight + gap;
            } else {
                int lineHeight = line.get(0).c.getPreferredSize().height;
                extraSpace = maxW - getRequiredLineWidth(line);
                if (extraSpace > 0) extraSpace = extraSpace / line.size();
                else extraSpace = 0;
                for (Element e : line) {
                    e.c.setBounds(x, y, e.c.getPreferredSize().width + extraSpace, lineHeight);
                    x += e.c.getPreferredSize().width + gap + extraSpace;
                }
                x = defX;
                y += lineHeight + gap;
            }
        }
    }

    private int getRequiredLineWidth (ArrayList<Element> line) {
        int result = gap; /* left gap */
        for (Element e : line) {
            result += e.c.getPreferredSize().width + gap;
        }
        return result;
    }

    public void removeLayoutComponent(Component comp) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public Dimension preferredLayoutSize(Container parent) {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public Dimension minimumLayoutSize(Container parent) {
        throw new UnsupportedOperationException("Not supported yet.");
    }



}
